package com.hbzhit.modules.sys.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hbzhit.common.exception.RRException;
import com.hbzhit.common.extension.BaseServiceImpl;
import com.hbzhit.common.utils.ShiroUtils;
import com.hbzhit.modules.enums.PeriodCycleEnum;
import com.hbzhit.modules.sys.dao.*;
import com.hbzhit.modules.sys.entity.*;
import com.hbzhit.modules.sys.service.*;
import com.hbzhit.modules.sys.vo.ProReportVO;
import lombok.SneakyThrows;
import org.apache.poi.ss.usermodel.DataFormat;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 项目填报表
 *
 * @author hbzhit
 * @date 2022-04-26 14:52:48
 **/
@Service("proReportService")
public class ProReportServiceImpl extends BaseServiceImpl<ProReportDao, ProReportEntity> implements ProReportService {

    @Resource
    private ProService proService;

    @Resource
    private ProUserService proUserService;

    @Resource
    private SysOrgService sysOrgService;

    @Resource
    private SysUserRoleService userRoleService;

    @Resource
    private ReportApprovalService reportApprovalService;

    @Resource
    private SysRoleService roleService;


    @Override
    //@Scheduled(cron = "0 0 * * * ?")
    //@Scheduled(cron = "0 0/5 * * * ?")
    public void pushTheReport() {
        //查询所有启动中且项目到期时间还未结束的项目
        List<ProEntity> proList = proService.list(new LambdaQueryWrapper<ProEntity>().eq(ProEntity::getStatus, 0).le(ProEntity::getProEndTime,DateUtil.today()));
        for (ProEntity pro : proList) {
            createReportForPro(pro, true);
        }
    }


    @SneakyThrows
    @Override
    @Transactional
    public ProEntity createReportForPro(ProEntity proEntity, boolean updatePlan) {
        List<ProReportEntity> reportEntityList = new ArrayList<>();
        //获取最后一次填报组时期，判断是否是今天，是今天则不在重复生成
        int count = this.count(Wrappers.<ProReportEntity>lambdaQuery().eq(ProReportEntity::getProId, proEntity.getId()).eq(ProReportEntity::getPeriodMark, DateUtil.today()));
        if (count > 0) return proEntity;

        SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm");
        Date nowTime = dateFormat.parse(dateFormat.format(DateUtil.date()));

        if (Objects.equals(proEntity.getProReportingCycle(), PeriodCycleEnum.MONTH.getCode())) {
            //月
            if (Objects.equals(proEntity.getProReportingDate(), DateUtil.dayOfMonth(DateUtil.date())) && !nowTime.before(dateFormat.parse(proEntity.getPushTime()))) {
                reportEntityList.addAll(createReport(proEntity));
            }
        } else if (Objects.equals(proEntity.getProReportingCycle(), PeriodCycleEnum.WEEK.getCode())) {
            //周
            if (Objects.equals(proEntity.getProReportingDate(), DateUtil.dayOfWeek(DateUtil.date())) && !nowTime.before(dateFormat.parse(proEntity.getPushTime()))) {
                reportEntityList.addAll(createReport(proEntity));
            }
        } else {
            //日
            if (!nowTime.before(dateFormat.parse(proEntity.getPushTime()))) {
                reportEntityList.addAll(createReport(proEntity));
            }
        }

        String reportGroupId = IdUtil.simpleUUID();
        reportEntityList.forEach(item -> item.setReportGroupId(reportGroupId));

        if (CollectionUtil.isNotEmpty(reportEntityList)) {
            if (!saveBatch(reportEntityList)) {
                throw new RRException("填报新增，失败！");
            }

            if (updatePlan) {
                proEntity.setReportGroupId(reportGroupId);
                proService.updateById(proEntity);
            }
        }

        return proEntity;
    }


    @Override
    public ProReportVO approvalList(String reportGroupId, String proId) {
        // 获取当前用户
        SysUserEntity currUser = ShiroUtils.getUser();
        //获取当前用户类型
        ProUserEntity proUser = proUserService.getOne(Wrappers.<ProUserEntity>lambdaQuery().eq(ProUserEntity::getUserId, currUser.getId()).eq(ProUserEntity::getProId, proId));

        //获取当前用户角色信息
        List<SysRoleEntity> sysRoleEntityList = userRoleService.queryRoleList(currUser.getId());
        List<String> roleNames = sysRoleEntityList.stream().map(SysRoleEntity::getRoleName).collect(Collectors.toList());

        ProReportVO proReportVO = new ProReportVO();
        proReportVO.setProInfoVO(proService.queryProInfo(Long.parseLong(proId)));

        List<ProReportVO.Fill> fillList = new ArrayList<>();

        if (roleNames.contains("交付总监") || proUser.getType() != 0) {
            fillList = this.baseMapper.selectReportList(reportGroupId, proId, null);
        } else {
            fillList = this.baseMapper.selectReportList(reportGroupId, proId, currUser.getId());
        }

        if (CollectionUtil.isEmpty(fillList)) return proReportVO;

        List<ProReportVO.Fill> memberList = fillList.stream().filter((ProReportVO.Fill f) -> f.getReporterType() == 0).collect(Collectors.toList());
        proReportVO.setFillMap(CollectionUtil.isNotEmpty(memberList) ? "项目成员汇报" : "待汇报", memberList);

        List<ProReportVO.Fill> mangerList = fillList.stream().filter((ProReportVO.Fill f) -> f.getReporterType() == 1).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(memberList))
            proReportVO.setFillMap(CollectionUtil.isNotEmpty(mangerList) ? "项目经理审批" : "待项目经理审批", mangerList);

        List<ProReportVO.Fill> deptList = fillList.stream().filter((ProReportVO.Fill f) -> f.getReporterType() == 2).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(mangerList))
            proReportVO.setFillMap(CollectionUtil.isNotEmpty(deptList) ? "部门经理审批" : "待部门经理审批", deptList);

        //获取交付总监审核结果
        Map<String, Object> majordomoAudit = this.baseMapper.selectAudit(reportGroupId, proId);
        if (ObjectUtil.isNotEmpty(majordomoAudit) && Integer.parseInt(majordomoAudit.get("bpmStatus").toString()) != 0) {
            ProReportVO.Fill fill = new ProReportVO.Fill();
            fill.setReportTime(DateUtil.parse(majordomoAudit.get("auditTime").toString(), "yyyy-MM-dd HH:mm:ss"));
            fill.setRealName(majordomoAudit.get("realName").toString());
            fill.setBpmStatus(Integer.parseInt(majordomoAudit.get("bpmStatus").toString()));
            fill.setCompleteTasks(majordomoAudit.get("message").toString());
            proReportVO.setFillMap("交付总监审批", ListUtil.toList(fill));
        } else {
            if (CollectionUtil.isNotEmpty(deptList)) proReportVO.setFillMap("待交付总监审批", new ArrayList<>());
        }
        return proReportVO;
    }

    @Override
    @Transactional
    public Boolean approvalProcess(Long reportId, Integer status, String scheduleTasks, String completeTasks) {

        // 获取当前用户
        SysUserEntity currUser = ShiroUtils.getUser();

        // 获取填报信息
        ProReportEntity proReport = getOne(Wrappers.<ProReportEntity>query().lambda().eq(ProReportEntity::getReporter, currUser.getId()).eq(ProReportEntity::getId, reportId));

        //如果填报显示已提交审批则不可重复操作
        if (proReport.getBpmStatus() >= 2) return false;
        //获取当前用户类型
        //ProUserEntity proUser = proUserService.getOne(Wrappers.<ProUserEntity>lambdaQuery().eq(ProUserEntity::getUserId, currUser.getId()).eq(ProUserEntity::getProId, proReport.getProId()));

        // 设置填写填报内容
        proReport.setScheduleTasks(scheduleTasks);
        proReport.setCompleteTasks(completeTasks);
        proReport.setReportTime(DateUtil.date());

        // 提交汇报
        if (status == 0) {
            proReport.setBpmStatus(1);
        }
        // 提交审批
        else if (status == 1) {
            if (proReport.getReporterType() == 1) {
                int count = count(Wrappers.<ProReportEntity>query().lambda()
                        .eq(ProReportEntity::getReporterType, 0).eq(ProReportEntity::getProId, proReport.getProId())
                        .lt(ProReportEntity::getBpmStatus, 2).eq(ProReportEntity::getReportGroupId, proReport.getReportGroupId()));
                if (count != 0) {
                    throw new RRException("无法提交审批，有组员还未提交审批！");
                } else {
                    // 项目经理提交审批后，将成员的审批状态改为审批通过
                    update(Wrappers.<ProReportEntity>update().lambda().set(ProReportEntity::getBpmStatus, 3).set(ProReportEntity::getApprover, currUser.getId()).set(ProReportEntity::getApproverTime, DateUtil.date())
                            .eq(ProReportEntity::getProId, proReport.getProId()).eq(ProReportEntity::getReporterType, 0).eq(ProReportEntity::getReportGroupId, proReport.getReportGroupId()));
                    proReport.setBpmStatus(2);
                }
            } else if (proReport.getReporterType() == 2) {
                int count = count(Wrappers.<ProReportEntity>query().lambda()
                        .eq(ProReportEntity::getReporterType, 1).eq(ProReportEntity::getProId, proReport.getProId())
                        .lt(ProReportEntity::getBpmStatus, 2).eq(ProReportEntity::getReportGroupId, proReport.getReportGroupId()));
                if (count != 0) {
                    throw new RRException("无法提交审批，项目经理未提交审批！");
                } else {
                    // 部门经理提交审批后，将项目经理的审批状态改为审批通过
                    update(Wrappers.<ProReportEntity>update().lambda().set(ProReportEntity::getBpmStatus, 3).set(ProReportEntity::getApprover, currUser.getId()).set(ProReportEntity::getApproverTime, DateUtil.date())
                            .eq(ProReportEntity::getProId, proReport.getProId()).eq(ProReportEntity::getReporterType, 1).eq(ProReportEntity::getReportGroupId, proReport.getReportGroupId()));
                    proReport.setBpmStatus(2);

                    //新建总监审批数据
                    ReportApprovalEntity reportApproval = new ReportApprovalEntity();
                    reportApproval.setGroupId(proReport.getReportGroupId());
                    reportApproval.setProId(Long.parseLong(proReport.getProId()));
                    reportApprovalService.save(reportApproval);
                }
            } else if (proReport.getReporterType() == 0) {
                proReport.setBpmStatus(2);
            }
        }
        return this.updateById(proReport);
    }

    @Override
    public List<ProReportEntity> queryMarkList(Long proId) {
        return this.list(Wrappers.<ProReportEntity>query().select("DISTINCT period_mark,report_group_id").lambda().eq(ProReportEntity::getProId, proId));
    }

    @Override
    public IPage<Map<String, Object>> proReportPage(Page page, Integer status) {
        // 获取当前用户
        SysUserEntity currUser = ShiroUtils.getUser();
        //获取当前用户角色列表
        List<SysRoleEntity> sysRoleEntityList = userRoleService.queryRoleList(currUser.getId());
        List<String> roleNames = sysRoleEntityList.stream().map(SysRoleEntity::getRoleName).collect(Collectors.toList());
        Map<String, Object> map = new HashMap<>();
        map.put("status", status);

        if (roleNames.contains("交付总监")) {
            map.put("roleType", 1);//交付总监查看
        } else {
            map.put("reporter", currUser.getId());
            map.put("roleType", 0); //其他人查看
        }
        return this.baseMapper.proReportPage(page, map);
    }


    private List<ProReportEntity> createReport(ProEntity pro) {
        List<ProReportEntity> proReportEntityList = new ArrayList<>();
        proUserService.list(new LambdaQueryWrapper<ProUserEntity>().eq(ProUserEntity::getProId, pro.getId()).eq(ProUserEntity::getIsDel, 0))
                .forEach(proUser -> {
                    ProReportEntity report = new ProReportEntity();
                    report.setPeriodMark(DateUtil.date(Calendar.getInstance()));
                    report.setProId(pro.getId().toString());
                    report.setBpmStatus(ProReportEntity.BPM_STATUS_IN_PROGRESS);
                    report.setReporter(proUser.getUserId().toString());
                    report.setReporterType(proUser.getType());
                    report.setOrgId(pro.getOrgId());
                    proReportEntityList.add(report);
                });
        return proReportEntityList;
    }

}
